import {
    Environment,
    Network,
    RecordSource,
    Store,
    Variables,
    RequestParameters,
    CacheConfig
} from "relay-runtime";
import {UploadableMap} from "relay-runtime/lib/network/RelayNetworkTypes";


/** 发请求到： 实际的某种的 后端服务器；
 * Relay requires developers to configure a "fetch" function that tells Relay how to load
 * the results of GraphQL queries from your server (or other data source). See more at
 * https://relay.dev/docs/en/quick-start-guide#relay-environment.
这个缓存\Relay\react-router-v6-with-relay-hooks-master机制和Modern Store 什么关系的？？
const oneMinute = 60 * 1000;
const cache = new QueryResponseCache({ size: 250, ttl: oneMinute });
   应当是两个概念；两个东西都能暂时存储。  像是一级缓存，二级缓存？
Network层次Cache 是底层的；生存周期时间很短，存储的查询结果条数比较少,是fetchRelay()函数简单缓存。
Relay层次RelayModernStore 是上层的Relay；存储时间有效期很长久，Environment空间Store存储能力不限制。
默认设置上不会使用Network层次Cache的；不要用QueryResponseCache()。
 */
async function fetchRelay(
    params: RequestParameters,
    variables: Variables,
    _cacheConfig: CacheConfig
) {
    /*
    这个缓存\Relay\react-router-v6-with-relay-hooks-master机制和Modern Store 什么关系的？？
      const queryId = operation.text || '';
      const isMutation = operation.operationKind === 'mutation';
      const isQuery = operation.operationKind === 'query';
      const forceFetch = cacheConfig?.force;
    const fromCache = cache.get(queryId, variables);
    if (isQuery && fromCache !== null && !forceFetch) {
        return fromCache;
    }*/
    //const REACT_APP_GITHUB_AUTH_TOKEN = process.env.REACT_APP_GITHUB_AUTH_TOKEN;
    // Fetch data from GitHub's GraphQL API:
    //很明显只能支持一个的服务端URL，不能允许多个 不同的 graphQL服务模型服务器。
    //若这里接入一个中间件进行分叉，查询变更等的 目的服务器根据什么规则分离？ 分配给不同的graphQL服务器。
    const response = await fetch(`${process.env.REACT_APP_BACK_END}/graphql`, {
        method: "POST",
        credentials: "include",
        headers: {
            //不需要Authorization: `Bearer ${REACT_APP_GITHUB_AUTH_TOKEN}`,
            "Content-Type": "application/json"
        },
        body: JSON.stringify({
            query: params.text,
            variables
        })
    });

    // Get the response as JSON
    const json = await response.json();

    // GraphQL returns exceptions (for example, a missing required variable) in the "errors"
    // property of the response. If any exceptions occurred when processing the request,
    // throw an error to indicate to the developer what went wrong.
    //数据提前获取，所以还未真正登录完成就发起请求了，服务端返回报错
    if (Array.isArray(json.errors)) {
        const messar= json.errors.map((error:any,i:number)=>error.message);
        throw new Error(
            `${JSON.stringify(messar)}`
        );
    }

    /*这个缓存\Relay\react-router-v6-with-relay-hooks-master机制和Modern Store 什么关系的？？
    if (isQuery && json && queryId !== '') {
        cache.set(queryId, variables, json);
    }
    if (isMutation) {
        cache.clear();
    }*/
    // Otherwise, return the full payload.
    return json;
}


// Export a singleton instance of Relay Environment configured with our network layer:
/*additional features such as request/response caching (enabled e.g. when cacheConfig.force is false) and
uploading form data for mutations (the uploadables parameter).
*/
//这个是单个后端服务端的吗？ 每一次登录后就会有一个实例
//这是实例！ new;
export default new Environment({
    network: Network.create(fetchRelay),
    store: new Store(new RecordSource(), {
        // This property tells Relay to not immediately clear its cache when the user
        // navigates around the app. Relay will hold onto the specified number of
        // query results, allowing the user to return to recently visited pages
        // and reusing cached data if its available/fresh.
        gcReleaseBufferSize: 10,
        //queryCacheExpirationTime?: 60000;和new QueryResponseCache({size:ttl:)完全不是一层次的？机制？不要用QueryResponseCache()。
        //If queryCacheExpirationTime not provided, only look at whether the referenced records have been invalidated.
        //前端Relay store缓存,默认 60分钟 超时重新查询。太短暂也不好，反正都必须有个缓存的==用户印象。 1个小时铁定更新。经过路由切换才能重新获取更新。
        queryCacheExpirationTime: 60 * 60 * 1000,
    })
});


/*
客户端扩展relay存储： 可利用来实现客户机状态管理，完全替换和抛弃react-redux的功能，也替换部分useState([队列])的需求。
文档  https://relay.dev/docs/next/guided-tour/updating-data/client-only-data/
redux一般是管理多个组件中共享数据的;类似useContext(<Context.Provider)和useReducer作用。而Relay提供的Store类比useContext(Provider)。
useReducer比useState更适用，state逻辑复杂且含多值或者下个state依赖于前state，可以向子组件传递dispatch而不是回调函数，返回一个在重新渲染之间不会改变的dispatch方法；
而Relay框架也能替换useReducer部分需求。
* */
